package br.ufrgs.meetapp.activities;

import java.util.ArrayList;
import java.util.Calendar;

import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import br.ufrgs.meetapp.control.BalloonItemizedOverlay;
import br.ufrgs.meetapp.models.Buddy;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;

public class ReportActivity extends MapActivity implements OnClickListener {
	
	public static Calendar calendarFrom;
	public static Calendar calendarTo;
	public static Buddy buddy;
	
	private Context context;
	private ArrayList<Buddy> buddyList;
	private MapView mapView;
	private MapController mapController;
	private MFTItemizedOverlay itemizedOverlay; 
	private Projection projection;
	private int selectedPointIndex = 0;
	private Button previousButton;
	private Button nextButton;
	private Button selectDatePeriodButton;
	private ImageButton zoomToSpamButton;
	private ProgressBar activityIndicator;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
		setContentView(R.layout.report_activity);

		context = this;

		buddyList = new ArrayList<Buddy>();

		setTitleBar();
		initializeViews();
	
	}
	
	@Override
	protected void onStart() {
		//TODO Remove this call and add it on post execute + call the async task
		populateMap();
		super.onStart();
	}
	
	/**
	 * Initialize views, map and overlay
	 */
	private void initializeViews() {
		previousButton = (Button)findViewById(R.id.report_activity_left_button);
		previousButton.setOnClickListener(this);
		
		nextButton = (Button)findViewById(R.id.report_activity_right_button);
		nextButton.setOnClickListener(this);
		
		selectDatePeriodButton = (Button)findViewById(R.id.report_activity_select_date_button);
		selectDatePeriodButton.setOnClickListener(this);
		
		zoomToSpamButton = (ImageButton)findViewById(R.id.report_activity_zoom_to_spam_button);
		zoomToSpamButton.setOnClickListener(this);
		
		activityIndicator = (ProgressBar)findViewById(R.id.report_activity_activity_indicator);
					

        mapView = (MapView) findViewById(R.id.report_activity_map_view);   
        mapController = mapView.getController();
 
        projection = mapView.getProjection();
        
        Drawable drawable = context.getResources().getDrawable(R.drawable.map_marker);
        itemizedOverlay = new MFTItemizedOverlay(drawable, mapView);
        mapView.getOverlays().add(itemizedOverlay);
	}
	
	/**
	 * Called to populate the map with the buddy history
	 */
	private void populateMap(){
		//TODO Get the real Buddy List
		itemizedOverlay.clear();
		buddyList = TrackOthersTabActivity.buddyList;
		
		for(Buddy buddy : buddyList){
			addBuddyToOverlay(buddy);
		}
		
		//Refresh Map		
		mapView.invalidate();
		
		zoomToBuddySpam();
	}
	
	/**
	 * Receives a buddy and add it to the overlay
	 * @param buddy
	 */
	private void addBuddyToOverlay(Buddy buddy){
		try{
			GeoPoint buddyGeoPoint; 
			buddyGeoPoint = new GeoPoint(buddy.getLatitude(), buddy.getLongitude());
			String date = "";
			
			try{
				date = buddy.getPositionDate().toLocaleString(); 
			}
			catch (Exception ex)
			{
				Log.i("MFT - ReportActivity ", "Error converting date: "+ex.getMessage());
			}
			
			itemizedOverlay.addOverlay(new OverlayItem(buddyGeoPoint, buddy.getBuddyName(), date));
		}
		catch (Exception ex)
		{
			Log.i("MFT - ReportMapActivity ", "Error creating map pin: "+ex.getMessage());
		}
	}
	
	/**
	 * Set the zoom and center of the map to show all buddies
	 */
	private void zoomToBuddySpam(){	
		int minLat = Integer.MAX_VALUE;
		int maxLat = Integer.MIN_VALUE;
		int minLon = Integer.MAX_VALUE;
		int maxLon = Integer.MIN_VALUE;

		for (Buddy currentBuddy : buddyList){
		      int lat = currentBuddy.getLatitude();
		      int lon = currentBuddy.getLongitude();

		      maxLat = Math.max(lat, maxLat);
		      minLat = Math.min(lat, minLat);
		      maxLon = Math.max(lon, maxLon);
		      minLon = Math.min(lon, minLon);
		 }

		mapController.zoomToSpan(Math.abs(maxLat - minLat), Math.abs(maxLon - minLon));
		mapController.animateTo(new GeoPoint( (maxLat + minLat)/2, 
		(maxLon + minLon)/2 )); 
	}
	
	
	/**
	 * Asynchronous to call the web service to get the buddy history
	 *
	 */
	private class GetBuddyHistoryTask extends AsyncTask<Void, Void, Void>{
		@Override
		protected void onPreExecute() {
			activityIndicator.setVisibility(View.VISIBLE);
			super.onPreExecute();
		}
		
		@Override
		protected Void doInBackground(Void... params) {
			// TODO call the web Service
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			activityIndicator.setVisibility(View.GONE);
			super.onPostExecute(result);
		}
		
	}
	
	@Override
	public void onClick(View view) {
		switch (view.getId()) {
		case R.id.report_activity_left_button:
			centerInNextPoint();
			break;
		case R.id.report_activity_right_button:
			centerInPreviousPoint();
			break;
		case R.id.report_activity_select_date_button:
			Intent intent = new Intent(context, ReportPeriodActivity.class);
			startActivity(intent);
			break;
		case R.id.report_activity_zoom_to_spam_button:
			zoomToBuddySpam();
			break;
		default:
			break;
		}
		
	}

	/**
	 * Center in the previous point
	 */
	private void centerInPreviousPoint() {
		selectedPointIndex --;
		if(selectedPointIndex < 0){
			selectedPointIndex = itemizedOverlay.size() - 1;
		}
		
		if (itemizedOverlay.size() != 0 && itemizedOverlay != null){
			mapController.animateTo(itemizedOverlay.getItem(selectedPointIndex).getPoint());
			itemizedOverlay.onTap(selectedPointIndex);
		}
		
	}

	/**
	 * Center in next point
	 */
	private void centerInNextPoint() {
		selectedPointIndex ++;
		if(selectedPointIndex >= itemizedOverlay.size()){
			selectedPointIndex = 0;
		}
		
		if (itemizedOverlay.size() != 0 && itemizedOverlay != null){
			mapController.animateTo(itemizedOverlay.getItem(selectedPointIndex).getPoint());
			itemizedOverlay.onTap(selectedPointIndex);
		}		
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	
	/***
	 * Sets the top bar
	 */
	private void setTitleBar() {
		TextView titleBarTitle;
		getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar);
		titleBarTitle = (TextView) findViewById(R.id.title_bar_text_title);		
		String title = context.getString(R.string.title_bar_report_activity) + " " + buddy.getBuddyName();		
		titleBarTitle.setText(title);
	}
	
	/**
	 * Custom ItemizedOverlay for the MFT project;
	 */
	private class MFTItemizedOverlay extends BalloonItemizedOverlay<OverlayItem>{
		private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
		
		/**
		 * Create a map overlay with a Default Marker
		 * 
		 * @param defaultMarker
		 * @param mapView
		 */
		public MFTItemizedOverlay(Drawable defaultMarker, MapView mapView) {
			super(boundCenter(defaultMarker), mapView);
			populate();
		}
		
		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			super.draw(canvas, mapView, shadow);
			
			Paint   mPaint = new Paint();
			mPaint.setDither(true);
			mPaint.setColor(Color.RED);
			mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
			mPaint.setStrokeJoin(Paint.Join.ROUND);
			mPaint.setStrokeCap(Paint.Cap.ROUND);
			mPaint.setStrokeWidth(2);
			
			if(size() > 2){
				for (int i = 0; i < size()-1; i++) {
					GeoPoint gP1 = this.getItem(i).getPoint();
					GeoPoint gP2 = this.getItem(i+1).getPoint();
					
					Point p1 = new Point();
					Point p2 = new Point();
					Path path = new Path();
					
					projection.toPixels(gP1, p1);
					projection.toPixels(gP2, p2);
					
					path.moveTo(p2.x, p2.y);
					path.lineTo(p1.x,p1.y);
					
					canvas.drawPath(path, mPaint);
				}					
			}
			
			
		}
		
		/**
		 * Add an overlay to overlay List
		 * @param overlay
		 */
		public void addOverlay(OverlayItem overlay) {
		    mOverlays.add(overlay);
		    populate();
		}

		@Override
		protected OverlayItem createItem(int i) {
			return mOverlays.get(i);
		}

		@Override
		public int size() {
			return mOverlays.size();
		}
		
		/**
		 * Removes all items from the overlay
		 */
		public void clear() {
	        mOverlays.clear();
	        populate();
	    }
		
		@Override
		protected boolean onBalloonTap(int index, OverlayItem item) {
			return true;
		}
		
	}

}
